import pika
import error
from configurate import MQ_CONFIG


class RabbitClient(object):
    __instance = None

    """ singleton """
    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            cls.__instance = super(RabbitClient, cls).__new__(cls, *args, **kwargs)
        return cls.__instance

    def __init__(self):
        self.connection = None
        self.channel = None
        self.exchange_type = MQ_CONFIG.get("exchange_type")

    def connect(self):
        try:
            if self.connection and not self.connection.is_closed:
                self.connection.close()

            credentials = pika.PlainCredentials(MQ_CONFIG.get("user"), MQ_CONFIG.get("passWord"))
            parameters = pika.ConnectionParameters(MQ_CONFIG.get("host"), MQ_CONFIG.get("port"), MQ_CONFIG.get("vHost"),
                                                   credentials)
            self.connection = pika.BlockingConnection(parameters)

            self.channel = self.connection.channel()

            # self.declare_exchange(exchange, exchange_type)
            self._declare_retry_queue()
        except Exception:
            raise error.MyError(error.ErrorCode.RABBIT_NONE)

    def declare_exchange(self, exchange, exchange_type=None):
        if exchange_type is not None:
            self.exchange_type = exchange_type
        self.channel.exchange_declare(exchange=exchange,
                                      exchange_type=self.exchange_type,
                                      durable=True)

    def declare_queue(self, queue):
        self.channel.queue_declare(queue=queue,
                                   durable=True, )

    def declare_binding(self, queue_name, exchange):
        self.channel.queue_bind(queue_name, exchange, queue_name)

    def _declare_retry_queue(self):
        """
        创建异常交换器和队列，用于存放没有正常处理的消息。
        :return:
        """
        self.channel.exchange_declare(exchange='RetryExchange',
                                      exchange_type='fanout',
                                      durable=True)
        self.channel.queue_declare(queue='RetryQueue',
                                   durable=True)
        self.channel.queue_bind('RetryQueue', 'RetryExchange', 'RetryQueue')

    def close_connection(self):
        self.connection.close()
